package com.hlg.xboot.aop;

import com.fasterxml.jackson.annotation.JsonFilter;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.introspect.Annotated;
import com.fasterxml.jackson.databind.introspect.JacksonAnnotationIntrospector;
import com.fasterxml.jackson.databind.ser.impl.SimpleBeanPropertyFilter;
import com.fasterxml.jackson.databind.ser.impl.SimpleFilterProvider;
import com.hlg.xboot.core.annotation.JsonExclude;
import com.hlg.xboot.core.annotation.JsonInclude;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.stereotype.Component;

/**
 * <p>Description: JSON属性过滤拦截器</p>
 * <p>Copyright: Copyright (c) 2016</p>
 * <p>Company: 中视数讯</p>
 * <p>Site: www.digi-zones.com</p>
 * <p>myblog: http://blog.csdn.net/xyang81</p>
 *
 * @author 杨信
 * @version 1.0
 * @date 2017/5/22
 */
@Component
public class JSONFilterAspectJ {

    @Autowired
    private MappingJackson2HttpMessageConverter jackson2HttpMessageConverter;

    @Pointcut("execution(* com.hlg.xboot.web.controller..*.*(..))")
    public void cutController(){}

    @Around("cutController()")
    public Object jsonFilter(ProceedingJoinPoint pjp) throws Throwable {
        MethodSignature msig = (MethodSignature) pjp.getSignature();
        JsonInclude include = msig.getMethod().getAnnotation(JsonInclude.class);
        JsonExclude exclude = msig.getMethod().getAnnotation(JsonExclude.class);
        boolean hasFilter = include != null || exclude != null;
        ObjectMapper mapper = jackson2HttpMessageConverter.getObjectMapper();
        mapper.setAnnotationIntrospector(new JacksonAnnotationIntrospector() {
            @Override
            public Object findFilterId(Annotated a) {
                Object annotated = a.getAnnotated().getDeclaredAnnotation(JsonFilter.class);
                return (hasFilter && annotated != null) ? super.findFilterId(a) : null;
            }
        });
        SimpleFilterProvider filterProvider = new SimpleFilterProvider();
        if (hasFilter) {
            if (include != null) {
                filterProvider.setDefaultFilter(SimpleBeanPropertyFilter.filterOutAllExcept(include.values()));
            } else if (exclude != null) {
                filterProvider.setDefaultFilter(SimpleBeanPropertyFilter.serializeAllExcept(exclude.values()));
            }
        } else {
            filterProvider.setDefaultFilter(SimpleBeanPropertyFilter.serializeAll());
        }
        mapper.setFilterProvider(filterProvider);

        return pjp.proceed();
    }
}
